<?php

 function usort_array_rev_segment($_array_seg1,$_array_seg2){
  return usort_rev_segment($_array_seg1[0],$_array_seg2[0]);
 }

 function usort_rev_segment($_seg1,$_seg2){
  $leni=$_seg1->__get_len();
  $lenj=$_seg2->__get_len();
  $lenmin=min($leni,$lenj);
  $offseti=$leni+$_seg1->__get_offset()-1;
  $offsetj=$lenj+$_seg2->__get_offset()-1;
  while($lenmin and ($_seg1->__get_char($offseti)==$_seg2->__get_char($offsetj))){
   $lenmin--;$offseti--;$offsetj--;
  }
  if(!$lenmin){return $leni-$lenj;}
  else{return ($_seg1->__get_char($offseti)<$_seg2->__get_char($offsetj))? -1 : 1;}
 }

 function usort_arrray_segment($_array_seg1,$_array_seg2){
  return usort_segment($_array_seg1[0],$_array_seg2[0]);
 }

 function ursort_segment($_seg1,$_seg2){
  return -usort_segment($_seg1,$_seg2);
 }

 function usort_segment($_seg1,$_seg2){
  $leni=$_seg1->__get_len();
  $lenj=$_seg2->__get_len();
  $lenmin=min($leni,$lenj);
  $offseti=$_seg1->__get_offset();
  $offsetj=$_seg2->__get_offset();
  while($lenmin and ($_seg1->__get_char($offseti)==$_seg2->__get_char($offsetj))){
   $lenmin--;$offseti++;$offsetj++;
  }
  if(!$lenmin){return $leni-$lenj;}
  else{return ($_seg1->__get_char($offseti)<$_seg2->__get_char($offsetj))? -1 : 1;}
 }

//tri par longueur
 function array_segment_usort1($i,$j){
  if($i->__get_len() < $j->__get_len()) return -1;
  else return ($i->__get_len() > $j->__get_len()) ? 1 : 0;
 }

//tri par position
 function array_segment_usort2($i,$j){
  if($i->__get_offset() < $j->__get_offset()) return -1;
  else return ($i->__get_offset()>$j->__get_offset()) ? 1 : 0;
 }

 function usort_array_segment_idstr($i,$j){
  if($i->__get_attribute("id_str") < $j->__get_attribute("id_str")) return -1;
  else return ($i->__get_attribute("id_str") > $j->__get_attribute("id_str")) ? 1 : array_segment_usort2($i,$j);
 }

 class segment{
  protected $str;
  protected $array_attributes=array();

  public function __construct(&$_str,$_offset,$_len,$_array_attributes=array()){
   $this->str=&$_str;
   $this->array_attributes["offset"]=$_offset;
   $this->array_attributes["len"]=$_len;
   foreach($_array_attributes as $name=>$value) $this->array_attributes[$name]=$value;
  }

  public function __destruct(){
   unset($this->str);
   $copy_array=$this->array_attributes;
   foreach($copy_array as $name=>$value) unset($this->array_attributes[$name]);
   unset($this->array_attributes);
  }

  public function __get_str(){return $this->str;}
  public function __get_char($_offset){return mb_substr($this->str,$_offset,1);}
  public function __get_offset(){return $this->array_attributes["offset"];}
  public function __get_offset_end(){return $this->__get_offset()+$this->__get_len();}
  public function __get_len(){return $this->array_attributes["len"];}
  public function __get_attribute($_name){return $this->array_attributes[$_name];}

  public function __set_attribute($_name,$_value){$this->array_attributes[$_name]=$_value;}

  public function __unset_attribute($_name){unset($this->array_attributes[$_name]);}

  public function __tostring(){
   return mb_substr($this->str,$this->array_attributes["offset"],$this->array_attributes["len"]);
  }

  public function __tostring_verbose(){
    $str_attrs="";
    foreach($this->array_attributes as $nom_attr=>$val_attr){
        $str_attrs.=$nom_attr.":".$val_attr." ";
    }
    $str_attr=rtrim($str_attr);
    return $this->__tostring()." [".$this->__get_offset()." ".$this->__get_len()." ".$str_attrs."]";
  }

  public function __fusion($_segment){
   $this->array_attributes["offset"]=min($this->array_attributes["offset"],$_segment->__get_offset());
   $this->array_attributes["len"]=max($this->__get_offset_end(),$_segment->__get_offset_end())-$this->array_attributes["offset"];
  }

 public function __does_include($_segment){
  return ($this->__get_offset_end()>=$_segment->__get_offset()) ? true : false;
 }

 public function __does_include2($_segment){
  $seg_start=$_segment->__get_offset();
  $seg_end=$seg_start+$_segment->__get_len();
  $start=$this->__get_offset();
  $end=$start+$this->__get_len();

  if($end>$seg_end and $start<$seg_end) return true;
  elseif($start<$seg_start and $end>$seg_start) return true;
  else return false;
 }

 public function __does_include3($_segment){
  $seg_start=$_segment->__get_offset();
  $seg_end=$seg_start+$_segment->__get_len();
  $start=$this->__get_offset();
  $end=$start+$this->__get_len();
  
  if($this->__get_attribute("id_str")!=$_segment->__get_attribute("id_str")) return false;
  elseif($seg_start>$start) return ($seg_start<$end) ? true : false;
  elseif($seg_end<$end) return ($seg_end<$end) ? true : false;
  elseif($seg_start<$start) return ($seg_end>$start) ? true : false;
  elseif($seg_end>$end) return ($seg_start<$end) ? true : false;
  else return false;
 }

  public function __does_include_strict($_segment){
   $offset_start=$_segment->__get_offset();
   $offset_end=$offset_start+$_segment->__get_len();
   $start=$this->__get_offset();
   $end=$start+$this->__get_len();
   return ($end>=$offset_end and $start<=$offset_start) ? true : false;
  }

 }

?>
